/* eslint-disable no-plusplus */
/* eslint-disable consistent-return */
import Taro, { getCurrentInstance } from '@tarojs/taro'
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { dataFetch } from '@pier88health/p8h-common'
import { GENDER_TYPE, NOTIFICATION_TYPE_NAME, STORAGE_KEY } from '@CONSTANTS/common'
import chatActions from '@ACTIONS/chat'
import messageActions from '@ACTIONS/message'
import profileActions from '@ACTIONS/profile'
import authActions from '@ACTIONS/auth'
import orderActions from '@ACTIONS/order'
import patientActions from '@ACTIONS/patient'
import meditationActions from '@ACTIONS/meditation'
import { initSocket } from '@UTILS/socket'
import webToast from '@UTILS/webToast'
import { ORDER_STATUS } from '@CONSTANTS/order'
import { ACQUIRE_CHANNEL_ENUM } from '@CONSTANTS/profile'
import { getPlatform, isWxBrowser, isWhiteList, handleClickTab, getPathname, isMiniprogramBrowser } from '@UTILS/common'
import { checkMPUpdate } from '@UTILS/wx'
import { getStorageSync } from '@UTILS/localStorage'
import {
  H5_AUTHORIZE_BASE_URL,
  TAB_PAGE,
  DECISION_PAGES,
  LANGUAGE,
  HIDDEN_FIXED_PAGES,
} from '@CONSTANTS/app'
import DBConfig from '@CONFIG/DBConfig'
import Scenes from '@NAVIGATION/scenes'

const MESSAGE_LIST_PAGE_NAME = 'MessageList'
const COLLECTION = 'message'
const { isWX, isWeb } = getPlatform()
global.AudioManager = isWX ? Taro.getBackgroundAudioManager() : {}
let WebNav
let HomeFixedButtonH5
if (process.env.TARO_ENV === 'h5') {
  HomeFixedButtonH5 = require('@COMPONENTS/WebNav/HomeFixedButton').default
  WebNav = require('@COMPONENTS/WebNav').default
}
const DIFF_TIME = 1000 * 60
@connect(
  state => ({
    newAlertNum: state.message.newAlertNum,
    newChatMessageCount: state.message.newChatMessageCount,
    currentSession: state.chat.currentSession,
    user: state.profile.user,
    isVisitor: state.profile.isVisitor,
    painLogPatient: state.patient.painLogPatient,
    currentMeditation: state.meditation.currentMeditation,
    outerPlayTime: state.meditation.outerPlayTime,
  }),
  {

    ...messageActions,
    ...chatActions,
    ...orderActions,
    ...profileActions,
    ...authActions,
    ...meditationActions,
    dispatchGetMyConsultations: patientActions.dispatchGetMyConsultations
  }
)
export default class Main extends Component {
  lastPath = ''

  async componentDidMount() {
    const { dispatchGetProfile, isVisitor, dispatchSetLoginSuccessInfo, dispatchGetSystemConfig } = this.props
    const token = await getStorageSync('token')
    isWeb && Taro.eventCenter.on('__taroRouterChange', this.onRouterChange)
    this.initUser()
    this.initWeChatH5OpenId()
    isWX && this.initialBackgroundAudioManager()
    checkMPUpdate()
    if (!token) {
      return
    }
    !isVisitor && dispatchGetProfile()
    dispatchSetLoginSuccessInfo()
    dispatchGetSystemConfig()
    setTimeout(() => {
      this.initWatch()
    })
    this.getMessageNumber()
    this.initWatchNetworkConnected()
    this.clearStoreData()
    Taro.eventCenter.on('CheckMsgConnect', this.onCheckMsgConnect)
  }

  clearStoreData =() => {
    !isWeb && Taro.removeStorage({ key: STORAGE_KEY.meditation_play_data })
  }

  onRouterChange = ({ toLocation }) => {
    if (TAB_PAGE.includes(this.lastPath) && TAB_PAGE.includes(toLocation.path)) {
      const { painLogPatient } = this.props
      const { Gender } = painLogPatient || {}
      const params = Scenes.dataCente === toLocation.path ? { Gender: Gender && GENDER_TYPE[Gender] || '未知' } : {}
      handleClickTab(toLocation.path, params)
    }
    this.lastPath = toLocation.path
  }

  onCheckMsgConnect = () => {
    if (this.isRetryConnectError) {
      this.initWatch()
    }
  }

  initWeChatH5OpenId = async () => {
    if (!isWxBrowser()) return
    if (isMiniprogramBrowser()) return

    // eslint-disable-next-line no-restricted-globals
    const currentHref = location.href
    if (!isWhiteList()) {
      Taro.showToast({ icon: 'none', title: 'dev和本地环境不支持支付' })
      return
    }
    const openId = await getStorageSync('wx_openid')
    if (openId) return
    if (currentHref.indexOf('home/index?code=') > -1) return
    const url = `${DBConfig.domainUrl}/pages/home/index`
    window.location.href = `${H5_AUTHORIZE_BASE_URL}&redirect_uri=${
      encodeURIComponent(url)}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`
  }

  async componentDidUpdate(prevProps) {
    const { isVisitor, user } = this.props
    if (!prevProps?.user?.p8Id && user?.p8Id) {
      this.initVisitorData()
    }
    if (!isVisitor && isVisitor !== prevProps.isVisitor) {
      this.initWatch()
      this.getMessageNumber()
    }
  }

  componentWillUnmount() {
    Taro.offNetworkStatusChange?.()
    isWeb && Taro.eventCenter.off('__taroRouterChange', this.onRouterChange)
    Taro.eventCenter.off?.('CheckMsgConnect', this.onCheckMsgConnect)
    this.socket?.ondisconnect()
    this.messageListener?.close()
    Taro.eventCenter.off()
  }

  initialBackgroundAudioManager = () => {
    Taro.eventCenter.on('playBgAudio', this.handlerPlay)
    Taro.eventCenter.on('stopBgAudio', this.handlerStop)
    Taro.eventCenter.on('changePage', this.handlerChangePage)
  }

  handlerChangePage = isMeditationDetail => {
    this.isMeditationDetail = isMeditationDetail
    if (this.isMeditationDetail) {
      this.timer && clearTimeout(this.timer)
    }
  }

  handlerPlay = time => {
    const { outerPlayTime, dispatchPlayMeditationAudio } = this.props
    if (!this.isMeditationDetail) {
      this.restTime = time || this.restTime
      this.finished = false
      this.timer && clearTimeout(this.timer)
      if (global.AudioManager.paused) return
      this.timer = setTimeout(() => {
        Taro.setStorageSync(STORAGE_KEY.meditation_white_noise, true)
        global.AudioManager.stop()
        this.finished = true
      }, (this.restTime - outerPlayTime) * 1000)
    }
    !time && dispatchPlayMeditationAudio()
  }

  handlerStop = finished => {
    this.timer && clearTimeout(this.timer)
    this.props.dispatchStopMeditationAudio(this.finished || finished)
  }

  retryConnectCount = 0

  isRetryConnectError = false

  initWatchNetworkConnected = () => {
    const { dispatchNetWorkStatus } = this.props
    Taro.onNetworkStatusChange(
      res => {
        const { isConnected } = res
        dispatchNetWorkStatus(isConnected)
      }
    )
  }

  initUser = async () => {
    const user = await getStorageSync('user')
    const { dispatchInitUser, dispatchVisitorLogin, dispatchGetNewBellAlertsNumber, dispatchGetUnViewedConsultationReport } = this.props
    if (user) {
      dispatchInitUser(user)
      !user.IsVisitor && dispatchGetNewBellAlertsNumber()
      !user.IsVisitor && dispatchGetUnViewedConsultationReport()
    } else {
      const { aC } = getCurrentInstance().router
      if (aC !== ACQUIRE_CHANNEL_ENUM.SpringRain) {
        dispatchVisitorLogin()
      }
    }
  }

  initWatch = () => {
    const { isVisitor } = this.props
    if (isVisitor) return
    if (isWX) {
      this.initWxWatch()
    }
    if (isWeb) {
      this.initWebSocket()
    }
  }

  initWxWatch = async () => {
    this.retryConnectCount++
    const { user } = this.props
    if (this.messageListener) await this.messageListener.close()

    if (!this.db) {
      this.db = Taro.cloud.database({
        env: ''
      })
    }
    const { command } = this.db
    const env = DBConfig.careEnvType.replace('stg', 'st')
    this.messageListener = this.db.collection(COLLECTION)
      .where({ UserId: user.p8Id, CreatedDate: command.gt(Date.now() - DIFF_TIME), Env: env })
      .watch({
        onChange: this.onRealtimeMessageSnapshot,
        onError: () => {
          // 重连5次
          this.isRetryConnectError = true
          console.log('watch: onError', this.retryConnectCount)
          if (this.retryConnectCount < 5) {
            this.initWatch()
          }
        }
      })
  }

  initWebSocket = () => {
    const { user } = this.props
    const { p8Id, ExternalIds } = user || {}
    if (!p8Id || Array.isArray(ExternalIds) && ExternalIds.length > 0) return
    this.socket?.ondisconnect()
    this.socket = initSocket(user?.p8Id, user.UserName)
    this.socket.on('notification', data => {
      if (!data) {
        return
      }
      const { UserId } = data
      if (UserId !== user.p8Id) return
      this.handleMessage(data)
    })
  }

  onRealtimeMessageSnapshot = snapshot => {
    const { type, docChanges } = snapshot
    this.retryConnectCount = 0
    this.isRetryConnectError = false
    if (type === 'init') return null
    if (docChanges && docChanges.length > 0 && docChanges[0].dataType === 'add') {
      this.handleMessage(docChanges[0].doc)
    }
  }

  initVisitorData = () => {
    const { dispatchCheckStatus } = this.props
    dispatchCheckStatus()
  }

  getMessageNumber = SessionId => {
    const {
      dispatchGetNewBellAlertsNumber, isVisitor, dispatchGetMyConsultations,
      dispatchGetUnViewedConsultationReport } = this.props
    if (isVisitor) return
    dispatchGetNewBellAlertsNumber()
    dispatchGetMyConsultations()
    dispatchGetUnViewedConsultationReport()
  }

  getSessionById = SessionId => {
    const { dispatchGetSessionById } = this.props
    dispatchGetSessionById(SessionId)
  }

  handleMessage = (data = {}) => {
    const {
      MessageId, SessionId, Type, ConsultationId, ConsultationType, PatientId, DoctorId
    } = data
    const {
      dispatchGetChatMessageById, dispatchGetSystemMessage, currentSession,
      dispatchGetNewBellAlertsNumber, dispatchGetConsultationInChatRoom, dispatchUpdateOrder,
      dispatchGetMyConsultations, dispatchGetUnViewedConsultationReport
    } = this.props

    const { Participants } = currentSession || {}
    const prePId = Participants?.[0]?.pid
    const preDId = Participants?.[1]?.uid
    const isSameChat = preDId === DoctorId  && prePId === PatientId 
    switch (Type) {
      case NOTIFICATION_TYPE_NAME.REJECT_PATIENT:
      case NOTIFICATION_TYPE_NAME.ACCEPT_PATIENT:
        dispatchGetNewBellAlertsNumber()
        dispatchGetSystemMessage()
        break
      case NOTIFICATION_TYPE_NAME.NEW_CARE_CHAT_MESSAGEN:
        if (!MessageId || !SessionId) return
        isWeb && isSameChat && this.handleWebToast(data)
        this.getMessageNumber(SessionId)
        this.getSessionById(SessionId)
        dispatchGetMyConsultations()
        isSameChat && dispatchGetChatMessageById(MessageId)
        break
      case NOTIFICATION_TYPE_NAME.SAVE_DOCTOR_ADVICE:
        dispatchGetConsultationInChatRoom(ConsultationId, SessionId)
        this.getSessionById(SessionId)
        dispatchUpdateOrder({ consultationId: ConsultationId, status: ORDER_STATUS.Closed, consulType: ConsultationType })
        break
      case NOTIFICATION_TYPE_NAME.ACCEPT_CONSULTATION:
        this.getMessageNumber()
        dispatchGetSystemMessage()
        this.getSessionById(SessionId)
        break
      case NOTIFICATION_TYPE_NAME.REJECT_CONSULTATION:
        dispatchGetNewBellAlertsNumber()
        dispatchGetSystemMessage()
        break
      case NOTIFICATION_TYPE_NAME.MED_RECORD:
      case NOTIFICATION_TYPE_NAME.CONSULTATION_REPORT:
        dispatchGetNewBellAlertsNumber()
        dispatchGetSystemMessage()
        dispatchGetUnViewedConsultationReport()
        break
      default:
        break
    }
  }

  handleWebToast = data => {
    const currentPage = getPathname().match('[^/]+(?!.*/)')[0]
    if (currentPage !== MESSAGE_LIST_PAGE_NAME) {
      this.showToast(data)
    }
  }

  showToast = () => {
    const { newAlertNum, newChatMessageCount } = this.props
    // webToast.show({ text: '提示来了' })
    const count = newAlertNum + newChatMessageCount + 1
    webToast.show({
      text: `您有${count}条新消息，请查看`,
    })
  }

  checkShowFixedButton = () => {
    if (!isWeb) {
      return false
    }
    const url = window.location.href
    const { language } = dataFetch.getQueryParams(url)
    const pathname = getPathname()
    if (LANGUAGE.EN === language && DECISION_PAGES.includes(pathname)) {
      return false
    }
    if (HIDDEN_FIXED_PAGES.includes(pathname)) {
      return false
    }
    if (pathname.includes('/subpackages/servicePack')) {
      return false
    }
    return !TAB_PAGE.includes(pathname)
  }

  render() {
    const { children } = this.props
    return (
      <>
        {isWeb ? <WebNav /> : null}
        {this.checkShowFixedButton() && <HomeFixedButtonH5 />}
        {children}
      </>
    )
  }
}
